Eloquent 是一個 ORM (object-relational mapper), 可以用來與整個資料互動, 或是代表其中一筆資料用來操作像是新增、刪除等
artisan 建立 eloquent
# 基本建立
php artisan make:model Product
# 建立同時新增 migration 檔案
php artisan make:model Product --migration
# 建立同時新增 factory 檔案
php artisan make:model Product --factory
# 其他參數建立 --constorller, --policy 等 ...
屬性
// 預設資料表會讀取轉換 Class 名稱的資料表
// e.g. Class ProducterModel -> product_model 資料表
// 設定 Model 的資料表名稱
protected $table = 'product';
// 預設會使用 id
// 若是其他名稱可自行設定 $primaryKey 屬性
protected $primaryKey = 'product_id';
// 當 primary key 不使用自動遞增時可設定屬性為 false
public $incrementing = false;
// 當 primary key 不使用數字時, 可以設定屬性為 string
protected $keyType = 'string';
# 設定不使用 created_at, updated_at
public $timestamps = false;
# 自訂記錄名稱
const CREATED_AT = 'created_date';
const UPDATED_AT = 'updated_date';
# 設定日期格式
protected $dateFormat = 'U';
// 設定資料庫連線方式
protected $connection = 'sqlite';
// 當在新建一筆資料時可以預設默認值
protected $attributes = [
'display' => false,
];
查詢方式
$products = Product::all();
$products = Product::where('category', 1)
->orderBy('name')
->take(10)
->get();
# 查詢
$product = Product::where('category', '1')->first();
# 重新取得
$fresh_product = $product->refresh();
# 修改資料後重整, 取消修改內容
$product->name = 'update name';
# 恢復到修改前的內容
$product->refresh();
$product = Product::where('category', 1)->get();
# e.g. reject() 類似 filters 當回傳值為 true 時會移除項目
$product = $product->reject(function ($product){
return !$product->display;
});
chunk()、chunkById() 分割查詢結果
Product::chunk(200, function($products) {
foreach( $producs as $product ) {
// 要做的事情 ...
}
});
# 使用 id 或其他指定來撈取資料
# 新增地個參數指定 id 欄位
Product::chunkById(200, function($products) {
foreach( $producs as $product ) {
// 要做的事情 ...
}
}, $column = 'id');
lazy 與 cursors
# lazy
Product::where('category', 1)
->lazyById(200, $column = 'id')
->each->update(['category', 11]);
# cursor
$products = Product::cursor()->filter(function ($product) {
# 返回售價超過 1000 元的商品
return $product->price > 1000;
});
設定軟刪除
use Illuminate\Database\Eloquent\SoftDeletes;
class Product extends Model
{
use SoftDeletes;
}
# 新增軟刪除
Schema::table('product', function(Blueprint $table){
$table->softDeletes();
});
# 移除軟刪除
Schema::table('product', function(Blueprint $table){
$table->dropSoftDeletes();
});
# trashed() 進行軟刪除
$product->trashed();
# 恢復軟刪除
$product->restore();
# 查詢已軟刪除資料
Product::withTrashed();
# 真刪除
$product->forceDelete();
SoftDeletes 搭配 Pruning Models 設定定期清除軟刪除
use Illuminate\Database\Eloquent\Prunable;
class Product extends Model {
use Prunable;
# 設定刪除條件, 回傳一個 \Illuminate\Database\Eloquent\Builder
public function prunable() {
return static::where('created_at', '<=', now()->subMonth());
}
# 設定當刪除時要執行的其他動作 e.g. 刪除商品圖片
public function pruning() {
// ...
}
}
protected function schedule(Schedule $schedule)
{
# 設定偵測 model 下有 Prunable 的 Class
$schedule->command('model:prune')->daily();
# 指定 Class, 通常是 Class 在不同資料夾
$schedule->command('model:prune', [
'--model' => [Product::class, Category:class],
])->daily();
# 排除某些 Class
$schedule->command('model:prune', [
'--except' => [Product::class, Category:class],
])->daily();
}
use Illuminate\Database\Eloquent\MassPrunable;
class Product extends Model {
use MassPrunable;
# 設定刪除條件, 回傳一個 \Illuminate\Database\Eloquent\Builder
public function prunable() {
return static::where('created_at', '<=', now()->subMonth());
}
}
Query Scopes
namespace App\Scopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
class TestScope implements Scope {
# 覆寫 apply 方法
public function apply(Builder $builder, Model $model) {
$builder->where('created_at', '<', now()->subYears(2000));
}
}
use App\Scopes\TestScope;
class Product extends Model {
# 也可以使用 Closure 用 static::addGlobalScope 設定
protected static function booted() {
static::addGlobalScope(new TestScope);
}
}
# 查詢結果
# select * from `product` where `created_at` < 0021-02-18 00:00:00
# 當有單獨搜尋不想要使用, 可用 withoutGlobalScopes 排除條件
Product::withoutGlobalScopes(TestScope::class)->get();
Local Scopes
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Product extends Model {
public function scopeNew($query) {
return $query->where('created_at', '>', date("Y-m-d H:i:s", strtotime("- 3 days")));
}
}
# 使用
Product::new()->order('created_at')->get();
比較兩個 Model 可以使用 is() 或 isNot()方法
$product->is($newProduct);
$product->isNot($newProduct);
namespace App\Models;
use App\Events\ProductDeleted;
use App\Events\ProductSaved;
use Illuminate\Database\Eloquent\Model;
class Product extends Model {
protected $dispatchesEvents = [
'saved' => ProductSaved::class,
'deleted' => ProductDeleted::class
];
}
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Product extends Model {
protected static function booted() {
static::created(function ($product) {
// ...
});
}
}
# 使用 artisan 設定 observer
php artisan make:observer ProductObserver --model=Product
# provider 內設定
use App\Models\Product;
use App\Observers\ProductObserver;
public function boot(){
Product::observe(ProductObserver::class);
}
# 或是可以在 provider 設定屬性 $observers
protected $observers = [
Product::class => [ProductObserver::class],
];
* 設定在資料交易完成後才可以執行
```php
# 設定在 observer Class 內
public $afterCommit = true;
```
$product = Product::withoutEvents(function () use () {
Product::where('id', '=', '1')->delete();
return Product::find(1)
});
b. 使用 {動作}Quietly() 方法
$product->saveQuietly();
$product->deleteQuietly();
$product->restoreQuietly();